<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Carbon\Carbon;

class Coupon extends Model
{
    use HasFactory;

    /**
     * 可批量赋值的属性
     */
    protected $fillable = [
        'name',
        'code',
        'type',
        'value',
        'min_purchase',
        'max_discount',
        'total_quantity',
        'used_quantity',
        'per_user_limit',
        'valid_days',
        'start_time',
        'end_time',
        'applicable_type',
        'applicable_ids',
        'stackable',
        'description',
        'usage_note',
        'is_active',
        'is_new_user_only',
        'sort_order',
    ];

    /**
     * 属性类型转换
     */
    protected $casts = [
        'value' => 'decimal:2',
        'min_purchase' => 'decimal:2',
        'max_discount' => 'decimal:2',
        'total_quantity' => 'integer',
        'used_quantity' => 'integer',
        'per_user_limit' => 'integer',
        'valid_days' => 'integer',
        'start_time' => 'datetime',
        'end_time' => 'datetime',
        'applicable_ids' => 'array',
        'stackable' => 'boolean',
        'is_active' => 'boolean',
        'is_new_user_only' => 'boolean',
        'sort_order' => 'integer',
    ];

    /**
     * 优惠券类型常量
     */
    const TYPE_FIXED = 'fixed';              // 固定金额
    const TYPE_PERCENT = 'percent';          // 百分比折扣
    const TYPE_SHIPPING = 'shipping';        // 包邮
    const TYPE_FULL_REDUCTION = 'full_reduction'; // 满减

    /**
     * 适用范围常量
     */
    const APPLICABLE_ALL = 'all';            // 全场
    const APPLICABLE_CATEGORY = 'category';  // 指定分类
    const APPLICABLE_PRODUCT = 'product';    // 指定商品

    /**
     * 获取用户优惠券
     */
    public function userCoupons(): HasMany
    {
        return $this->hasMany(UserCoupon::class);
    }

    /**
     * 获取分发记录
     */
    public function distributions(): HasMany
    {
        return $this->hasMany(CouponDistribution::class);
    }

    /**
     * 作用域：启用的优惠券
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * 作用域：可用的优惠券（时间范围内）
     */
    public function scopeAvailable($query)
    {
        $now = Carbon::now();
        return $query->where('is_active', true)
            ->where(function ($q) use ($now) {
                $q->whereNull('start_time')
                    ->orWhere('start_time', '<=', $now);
            })
            ->where(function ($q) use ($now) {
                $q->whereNull('end_time')
                    ->orWhere('end_time', '>=', $now);
            });
    }

    /**
     * 作用域：指定类型
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }

    /**
     * 访问器：是否可用
     */
    public function getIsAvailableAttribute(): bool
    {
        if (!$this->is_active) {
            return false;
        }

        $now = Carbon::now();

        // 检查开始时间
        if ($this->start_time && $this->start_time->gt($now)) {
            return false;
        }

        // 检查结束时间
        if ($this->end_time && $this->end_time->lt($now)) {
            return false;
        }

        // 检查数量限制
        if ($this->total_quantity > 0 && $this->used_quantity >= $this->total_quantity) {
            return false;
        }

        return true;
    }

    /**
     * 访问器：剩余数量
     */
    public function getRemainingQuantityAttribute(): int
    {
        if ($this->total_quantity == 0) {
            return -1; // 无限制
        }

        return max(0, $this->total_quantity - $this->used_quantity);
    }

    /**
     * 访问器：适用范围文本
     */
    public function getApplicableScopeTextAttribute(): string
    {
        return match ($this->applicable_type) {
            self::APPLICABLE_ALL => '全场通用',
            self::APPLICABLE_CATEGORY => '指定分类',
            self::APPLICABLE_PRODUCT => '指定商品',
            default => '未知',
        };
    }

    /**
     * 访问器：类型文本
     */
    public function getTypeTextAttribute(): string
    {
        return match ($this->type) {
            self::TYPE_FIXED => '立减券',
            self::TYPE_PERCENT => '折扣券',
            self::TYPE_SHIPPING => '包邮券',
            self::TYPE_FULL_REDUCTION => '满减券',
            default => '未知',
        };
    }

    /**
     * 访问器：优惠描述
     */
    public function getDiscountDescAttribute(): string
    {
        return match ($this->type) {
            self::TYPE_FIXED => "立减¥{$this->value}",
            self::TYPE_PERCENT => "{$this->value}折",
            self::TYPE_SHIPPING => "免运费",
            self::TYPE_FULL_REDUCTION => "满¥{$this->min_purchase}减¥{$this->value}",
            default => '',
        };
    }

    /**
     * 检查用户是否可以领取
     *
     * @param int $userId
     * @return array ['can_receive' => bool, 'reason' => string]
     */
    public function canUserReceive(int $userId): array
    {
        // 检查是否启用
        if (!$this->is_active) {
            return ['can_receive' => false, 'reason' => '优惠券暂不可用'];
        }

        // 检查新用户限制
        if ($this->is_new_user_only) {
            $user = User::find($userId);
            if ($user && $user->orders()->exists()) {
                return ['can_receive' => false, 'reason' => '此券仅限新用户领取'];
            }
        }

        // 检查领取次数限制
        if ($this->per_user_limit > 0) {
            $receivedCount = UserCoupon::where('user_id', $userId)
                ->where('coupon_id', $this->id)
                ->count();

            if ($receivedCount >= $this->per_user_limit) {
                return ['can_receive' => false, 'reason' => '已达到领取上限'];
            }
        }

        // 检查库存
        if ($this->total_quantity > 0 && $this->used_quantity >= $this->total_quantity) {
            return ['can_receive' => false, 'reason' => '优惠券已抢光'];
        }

        return ['can_receive' => true, 'reason' => ''];
    }

    /**
     * 计算优惠金额
     *
     * @param float $orderAmount 订单金额
     * @param array $items 订单商品
     * @return array ['can_use' => bool, 'discount' => float, 'reason' => string]
     */
    public function calculateDiscount(float $orderAmount, array $items): array
    {
        // 检查最低消费
        if ($orderAmount < $this->min_purchase) {
            return [
                'can_use' => false,
                'discount' => 0,
                'reason' => "需满¥{$this->min_purchase}元才能使用"
            ];
        }

        // 检查适用商品
        if ($this->applicable_type !== self::APPLICABLE_ALL) {
            $applicable = $this->checkApplicableItems($items);
            if (!$applicable) {
                return [
                    'can_use' => false,
                    'discount' => 0,
                    'reason' => '订单中没有可用此优惠券的商品'
                ];
            }
        }

        $discount = 0;

        // 计算折扣
        switch ($this->type) {
            case self::TYPE_FIXED:
            case self::TYPE_FULL_REDUCTION:
                $discount = min($this->value, $orderAmount);
                break;

            case self::TYPE_PERCENT:
                $discount = $orderAmount * ($this->value / 100);
                if ($this->max_discount && $discount > $this->max_discount) {
                    $discount = $this->max_discount;
                }
                break;

            case self::TYPE_SHIPPING:
                // 包邮券的折扣在运费中体现
                $discount = 0;
                break;
        }

        return [
            'can_use' => true,
            'discount' => round($discount, 2),
            'reason' => ''
        ];
    }

    /**
     * 检查商品是否适用
     *
     * @param array $items
     * @return bool
     */
    protected function checkApplicableItems(array $items): bool
    {
        if ($this->applicable_type === self::APPLICABLE_ALL) {
            return true;
        }

        if (empty($this->applicable_ids)) {
            return false;
        }

        foreach ($items as $item) {
            if ($this->applicable_type === self::APPLICABLE_PRODUCT) {
                // 检查商品ID
                if (in_array($item['product_id'], $this->applicable_ids)) {
                    return true;
                }
            } elseif ($this->applicable_type === self::APPLICABLE_CATEGORY) {
                // 检查分类ID
                $product = Product::find($item['product_id']);
                if ($product) {
                    $categoryIds = $product->categories->pluck('id')->toArray();
                    if (array_intersect($categoryIds, $this->applicable_ids)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * 增加已使用数量
     */
    public function incrementUsedQuantity(): void
    {
        $this->increment('used_quantity');
    }

    /**
     * 减少已使用数量
     */
    public function decrementUsedQuantity(): void
    {
        $this->decrement('used_quantity');
    }
}
